package org.myorg;

public class NGA {
	static int best_p;
	static double best_v;
	static NPeople best_people;
	
	public static void ga(int geneLength, int peopleNum, double p_cross,
			double p_mut, int i_num,Fc function) {
		NPeople my_p = new NPeople(peopleNum,geneLength);
		NEvolution my_e = new NEvolution(0.1, p_cross, p_mut, my_p, function);
		
		for (int i=0; i < i_num; i++) {
			my_p.caculateFitness(function);
			my_e.select();
			my_e.crossOver();
			my_e.mutation();
		}
		best_people=my_p;
		best_p = my_p.getBest(function);
		
		System.out.println("the best individual is "+my_p.getPersons()[best_p].getGene());
		System.out.println("the best value is "+my_p.getPersons()[best_p].getFitness());
	}
}

class NPeople {
	public int p_num;
	private Ps persons[];
	
	public NPeople(NPeople people) {
		this.p_num = people.p_num;
		this.persons = people.persons;
}
	
	public NPeople(int num, int length) {
		p_num = num;
		persons = new Ps[num];
		
		for(int i = 0; i < num; i++) {
			persons[i] = new Ps(length);
		}
		//System.out.println(persons[0]);
	}
	
	public void caculateFitness(Fc function) {
		for (int i = 0; i < p_num; i++) {
			function.caculate(persons[i]);
		}
	}
	
	public int getBest(Fc function) {
		int res = 0;
		for (int i = 0; i<p_num; i++) {
			if(function.better(persons[i],persons[res]))
				res = i;
		}
		return res;
	}
	

	public Ps[] getPersons() {
		return persons;
	}
	
}

class NEvolution {
	/*
	 * 
	 * @param p_s 选择算子
	 * @param p_c 交叉算子 
	 * @param p_m 变异算子
	 */
	private double ps;
	private double pc;
	private double pm;
	private NPeople people;
	private Fc fun;
	
	public NEvolution(double p_s, double p_c, double p_m, NPeople p, Fc fun) {
		ps = p_s;
		pc = p_c;
		pm = p_m;
		people = p;
		this.fun = fun;
	}
	
	/*
	 * 使用锦标赛的选择算法
	 */
	public void select() {
		for (int i = 0; i < people.p_num; i++) {
			int pos1 = (int) (Math.random()*people.p_num);
			int pos2 = (int) (Math.random()*people.p_num);
			if (fun.better(people.getPersons()[pos1],people.getPersons()[pos2]))
				people.getPersons()[i] = people.getPersons()[pos1];
			else
				people.getPersons()[i] = people.getPersons()[pos2];
		}
	}
	
	/*
	 * 交叉
	 */
	public void crossOver() {
		for (int i=0; i < (int) (pc*people.p_num); i++) {
			int pos1 = (int) (Math.random()*people.p_num);
			int pos2 = (int) (Math.random()*people.p_num);
			int cross_pos = (int) (Math.random()*people.getPersons()[0].length);
			
			Ps temp1 = Ps.linkGene(people.getPersons()[pos1].getGene(0,cross_pos),
					people.getPersons()[pos2].getGene(cross_pos));
			
			people.getPersons()[pos2] = Ps.linkGene(people.getPersons()[pos2].getGene(0,cross_pos),
					people.getPersons()[pos1].getGene(cross_pos));
						
			people.getPersons()[pos1] = temp1;
			
		}
	}
	
	/*
	 * 变异
	 */
	public void mutation() {
		for(int i = 0; i < (int) (pm*people.p_num); i++) {
			int pos = (int) (Math.random()*people.p_num);
			int mut_pos = (int) (Math.random()*people.getPersons()[pos].length);
							
			if (people.getPersons()[pos].geneAt(mut_pos) == '0') {
				people.getPersons()[pos].setGene(mut_pos, '1');
			} else {
				people.getPersons()[pos].setGene(mut_pos, '0');
			}
		}
	}
}

